#include "idatagram_factory.hpp"

namespace datagram
{
	int IDatagramFactory::decode(ListBuffer & listbuffer, IDatagram *& datagram)
	{
		if (!frame(listbuffer))
		{
			return -1;
		}

		Streamer streamer(Streamer::OSTREAMER, listbuffer);
		uint32_t type = get_type(listbuffer);

		return decode(type, streamer, datagram);
	}

	void IDatagramFactory::encode(ListBuffer & listbuffer, IDatagram * datagram)
	{
		uint32_t      nbytes    = listbuffer.bytes_count();

		buffer::Buffer * buffer = listbuffer.tail();
		byte *           waddr  = buffer->write_addr();

		Streamer streamer(Streamer::ISTREAMER, listbuffer);

		encode(datagram->datagram_type(), streamer, datagram);

		nbytes = listbuffer.bytes_count() - nbytes;
		listbuffer.put(*buffer, waddr, nbytes);
	}

	bool IDatagramFactory::frame(ListBuffer & listbuffer)
	{
		return (get_length(listbuffer) <= (uint32_t)listbuffer.bytes_count());
	}

	uint32_t IDatagramFactory::get_magic(ListBuffer & listbuffer)
	{
		if (listbuffer.bytes_count() < IDatagram::LENGTH)
		{
			return uint32_t(-1);
		}
		uint32_t magic = 0;
		listbuffer.get(IDatagram::MAGIC_POS, magic);
		return magic;
	}

	uint32_t IDatagramFactory::get_length(ListBuffer & listbuffer)
	{
		if (listbuffer.bytes_count() < IDatagram::LENGTH)
		{
			return uint32_t(-1);
		}
		uint32_t length = 0;
		listbuffer.get(IDatagram::LENGTH_POS, length);
		return length;
	}

	uint32_t IDatagramFactory::get_type(ListBuffer & listbuffer)
	{
		if (listbuffer.bytes_count() < IDatagram::LENGTH)
		{
			return uint32_t(-1);
		}
		uint32_t type = 0;
		listbuffer.get(IDatagram::TYPE_POS, type);
		return type;
	}
};

